{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 71,
   "metadata": {},
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import random\n",
    "import warnings\n",
    "from sklearn.preprocessing import LabelEncoder,MinMaxScaler,OneHotEncoder\n",
    "warnings.filterwarnings(\"ignore\")#忽略警告"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 1.下载数据DRUG1n.csv，用Python语言实现K-均值算法。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "数据导入及预处理"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0.13559322033898308 0.0 1.0 1.0 0.7385087158709429 0.18799986614463077\n",
      " 0.0 0.0 0.0 0.0 1.0] (200, 11)\n"
     ]
    }
   ],
   "source": [
    "data=np.array(pd.read_csv('DRUG1n.csv',header=0))# \n",
    "guiyi = MinMaxScaler()\n",
    "data[data=='F']=0.0\n",
    "data[data=='M']=1.0\n",
    "data[data=='HIGH']=1.0\n",
    "data[data=='NORMAL']=0.5\n",
    "data[data=='LOW']=0.0\n",
    "one_hot_label = LabelEncoder().fit_transform(data[:,-1])#调用独热编码方法对特征进行独热编码\n",
    "one_hot=OneHotEncoder().fit_transform(one_hot_label.reshape(-1,1)).toarray()\n",
    "data=np.hstack((guiyi.fit_transform(data[:,0].reshape(-1,1)),data[:,1:4],\n",
    "guiyi.fit_transform(data[:,4].reshape(-1,1)),guiyi.fit_transform(data[:,5].reshape(-1,1)),one_hot))\n",
    "print(data[0],data.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "初始化随机质心函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "metadata": {},
   "outputs": [],
   "source": [
    "def Core_point(data,k):\n",
    "\tnumSamples, dim = data.shape[0],data.shape[1]\n",
    "\tcentroids = np.zeros((k, dim))\n",
    "\tfor i in range(k):\n",
    "\t\tindex = int(random.uniform(0, numSamples))\n",
    "\t\tcentroids[i, :] = data[index, :]\n",
    "\treturn centroids"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0.79661017, 1.        , 0.5       , 1.        , 0.64590148,\n",
       "        0.42714922, 0.        , 0.        , 0.        , 0.        ,\n",
       "        1.        ],\n",
       "       [0.3220339 , 1.        , 0.5       , 1.        , 0.25862936,\n",
       "        0.11396112, 0.        , 0.        , 0.        , 0.        ,\n",
       "        1.        ],\n",
       "       [0.76271186, 1.        , 0.5       , 1.        , 0.69978554,\n",
       "        0.5221698 , 0.        , 0.        , 0.        , 0.        ,\n",
       "        1.        ]])"
      ]
     },
     "execution_count": 74,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Core_point(data,3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "定义欧式距离函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "metadata": {},
   "outputs": [],
   "source": [
    "def Distance(a,b):\n",
    "    return np.sqrt(np.sum(np.power(a - b, 2)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2.0884135003975093"
      ]
     },
     "execution_count": 76,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Distance(data[0],data[1])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "聚类kmeans方法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "metadata": {},
   "outputs": [],
   "source": [
    "def kmeans(data,k=1):\n",
    "    clusterAssment=np.mat(np.zeros((data.shape[0],2)))# 创建一个二阶矩阵，第一行存储集群，第二行存储距离\n",
    "    flag=True#判断各点的集群是否不再改变\n",
    "\n",
    "    # 初始化质心\n",
    "    corepoint=Core_point(data,k)\n",
    "\n",
    "    while flag:\n",
    "        flag=False\n",
    "        for i in range(data.shape[0]):\n",
    "            minDistance=100000.0\n",
    "            minIndex=0\n",
    "            # 寻找质心\n",
    "            for j in range(k):\n",
    "                dis=Distance(data[i,:],corepoint[j,:])\n",
    "                if minDistance>dis:\n",
    "                    minDistance=dis\n",
    "                    minIndex=j\n",
    "            #更新集群\n",
    "            if clusterAssment[i,0]!=minIndex:\n",
    "                flag=True\n",
    "                clusterAssment[i,:]=minIndex,minDistance\n",
    "        \n",
    "        # 更新质心,取该集群当前参数的平均值作为质心\n",
    "        for i in range(k):\n",
    "            pointsInCluster = data[np.nonzero(clusterAssment[:, 0].A == j)[0]]\n",
    "            corepoint[j, :] = np.mean(pointsInCluster, axis = 0)\n",
    "\n",
    "    print('cluster has finished!')\n",
    "    return corepoint,clusterAssment\n",
    "            \n",
    "    "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "定义代价函数（用的是点到质心的平均距离）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "metadata": {},
   "outputs": [],
   "source": [
    "def cost(clusterAssment):\n",
    "    return np.mean(clusterAssment[:,1])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "聚类"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 98,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "cluster has finished!\n",
      "0.8387593411112245\n"
     ]
    }
   ],
   "source": [
    "k=3\n",
    "corepoint,clusterAssment=kmeans(data,k)\n",
    "cost_cluster=cost(clusterAssment)\n",
    "print(cost_cluster)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 2.针对不同的K，分别随机选择不同的初始聚类中心，计算聚类结果的代价函数，并给出相对较优的聚类结果。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "k=2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 102,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "cluster has finished!\n",
      "0.9672832682844811\n"
     ]
    }
   ],
   "source": [
    "k=2\n",
    "corepoint,clusterAssment=kmeans(data,k)\n",
    "cost_cluster=cost(clusterAssment)\n",
    "print(cost_cluster)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "k=4"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 105,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "cluster has finished!\n",
      "0.9418193609465629\n"
     ]
    }
   ],
   "source": [
    "k=4\n",
    "corepoint,clusterAssment=kmeans(data,k)\n",
    "cost_cluster=cost(clusterAssment)\n",
    "print(cost_cluster)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "k=5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 108,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "cluster has finished!\n",
      "0.9703280070288294\n"
     ]
    }
   ],
   "source": [
    "k=5\n",
    "corepoint,clusterAssment=kmeans(data,k)\n",
    "cost_cluster=cost(clusterAssment)\n",
    "print(cost_cluster)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "k=10"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 112,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "cluster has finished!\n",
      "0.7653089896539466\n"
     ]
    }
   ],
   "source": [
    "k=10\n",
    "corepoint,clusterAssment=kmeans(data,k)\n",
    "cost_cluster=cost(clusterAssment)\n",
    "print(cost_cluster)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "interpreter": {
   "hash": "0ea2ea13f89004d253f237dbfddddbdca6ade9e7c69d0cba8f71d034288dfba7"
  },
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
